package com.tfjybj.itoo.exam.provider.service.impl;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.dmsdbj.itoo.tool.base.service.impl.BaseServicePlusImpl;
import com.dmsdbj.itoo.tool.business.ItooResult;
import com.dmsdbj.itoo.tool.constantutil.YearSemester;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tfjybj.itoo.exam.entity.*;
import com.tfjybj.itoo.exam.model.*;
import com.tfjybj.itoo.exam.provider.dao.AssessmentAdviceDao;
import com.tfjybj.itoo.exam.provider.dao.EvaluationPaperDao;
import com.tfjybj.itoo.exam.provider.dao.EvaluationRecordDao;
import com.tfjybj.itoo.exam.provider.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.tfjybj.itoo.exam.provider.until.questionNaireConstants.adviceType;

/**
 * TeEvaluationPaperService接口实现类
 * ${base}表
 *
 * @author 杨江涛
 * @version 2.0.0
 * @since 2.0.0 2018-12-18 18:19:48
 */
@Service("teEvaluationPaperService")
@Slf4j
public class EvaluationPaperServiceImpl extends BaseServicePlusImpl<EvaluationPaperDao, EvaluationPaperEntity> implements EvaluationPaperService {
    /**
     * 问卷key
     */
    private static final String QUESTIONNAIRE_REDIS_INFO = "QUESTIONNAIRE_REDIS_INFO";

    @Resource
    private EvaluationPaperDao evaluationPaperDao;
    @Resource
    private EvaluationMainService evaluationMainService;
    @Resource
    private QuestionTypeService questionTypeService;
    @Resource
    private EvaluationPaperService evaluationPaperService;

    @Resource
    private EvaluationPaperDetailService evaluationPaperDetailService;

    @Resource
    private EvaluationSubService evaluationSubService;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private EvaluationRecordService teEvaluationRecordService;

    @Resource
    private EvaluationRecordDao teEvaluationRecordDao;

    @Resource
    private AssessmentAdviceService assessmentAdviceService;

    @Resource
    private AssessmentAdviceDao assessmentAdviceDao;


    @Override
    public QuestionNaireAllInfoModel queryTeEvaluationPaper() {
        return evaluationPaperDao.queryTeEvaluationPaper();
    }

    //endregion

    /* **********************************以下为非模板生成的内容********************************* */


    /**
     * 查询已有答题记录的课程问卷结果集合
     *
     * @return teEvaluationPaperModels
     * @author 杨晓慧
     * @since 2.0.0 2018年12月22日14:50:18
     */
    @Override
    public PageInfo<EvaluationPaperModel> queryCourseEvaluationPaperList(Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<EvaluationPaperModel> evaluationPaperModels = evaluationPaperDao.queryCourseEvaluationPaperList();
        return new PageInfo<>(evaluationPaperModels);
    }


    /**
     * 查询问卷
     *
     * @return questionNaireAllInfoModel
     * @author 杨晓慧
     * @since 2.0.0 2018年12月23日 12:37:47
     */
    @Override
    public ItooResult findQuestionNaire(String paperId, String courseId, String studentId, String schoolYearId) {
        //1.定义问卷内容实体返给前端用
        QuestionNaireAllInfoModel questionNaireAllInfoModel = new QuestionNaireAllInfoModel();
        //问卷基本信息
        final EvaluationPaperEntity evaluataionbyId = evaluationPaperService.getById(paperId);
        BeanUtils.copyProperties(evaluataionbyId, questionNaireAllInfoModel);
        questionNaireAllInfoModel.setPaperId(evaluataionbyId.getId());

        List<EvaluationPaperDetailModel> teEvaluationPaperDetailModels;
        //  2.得到指定某一个问卷所有详情(题型)
        teEvaluationPaperDetailModels = evaluationPaperDetailService.queryTeEvaluationPaperDetail(paperId);
        // 2.1 将问卷所有试题排序
        teEvaluationPaperDetailModels.sort(Comparator.comparing(EvaluationPaperDetailModel::getQuestionOrder));

        // 2.2 查询出所有试题类型，放入到map中，key为题型id，value为题型信息
        List<QuestionTypeModel> questionTypeModelList = questionTypeService.queryAllQuestionType();
        Map<String, QuestionTypeModel> questionTypeModelMap = new HashMap<>(questionTypeModelList.size() * 2);
        questionTypeModelList.forEach(
                q -> questionTypeModelMap.put(q.getId(), q)
        );
        // 3.查询学生答题记录
        List<EvaluationRecordModel> teEvaluationRecordModels = evaluationPaperDetailService.queryStudentEvaluationRecord(paperId, courseId, studentId, schoolYearId);
        Map<String, EvaluationRecordModel> teEvaluationRecorMap = new HashMap<>(teEvaluationRecordModels.size() * 2);
        teEvaluationRecordModels.forEach(tr -> {
            //将学生的答题记录按题干id+选项id的格式放入hashMap
            teEvaluationRecorMap.put(tr.getEvaluationMainId() + tr.getEvaluationSubId(), tr);
        });

        if (teEvaluationRecorMap.size() > 0) {
            // 3.1 学生答题记录不为空，需要做已答题回显
            teEvaluationPaperDetailModels.forEach(
                    tp -> {
                        tp.getEvaluationSubModelList().sort(Comparator.comparing(EvaluationSubModel::getOptionOrder));
                        QuestionTypeModel questionTypeModel = questionTypeModelMap.get(tp.getQuestionTypeId());
                        tp.setQuestionCode(questionTypeModel.getQuestionCode());
                        tp.setQuestionTypeName(questionTypeModel.getQuestionTypeName());

                        List<EvaluationSubModel> evaluationSubModelList = tp.getEvaluationSubModelList();
                        evaluationSubModelList.forEach(
                                tes -> {
                                    EvaluationRecordModel teEvaluationRecordModel = teEvaluationRecorMap.get(tes.getEvaluationMainId() + tes.getOptionId());
                                    if (teEvaluationRecordModel == null) {
                                        tes.setAnswer("false");
                                    } else {
                                        tes.setAnswer("true");
                                        tp.setDone(true);
                                    }
                                }
                        );
                    }
            );
            log.info("学生刷新页面回显答题记录成功！");
        } else {
            // 3.2 学生答题记录为空时，显示问卷详情即可
            teEvaluationPaperDetailModels.forEach(paperDetails -> {
                // 每道题的选项按照OptionOrder进行排序
                paperDetails.getEvaluationSubModelList().sort(Comparator.comparing(EvaluationSubModel::getOptionOrder));
                QuestionTypeModel questionTypeModel = questionTypeModelMap.get(paperDetails.getQuestionTypeId());
                paperDetails.setQuestionCode(questionTypeModel.getQuestionCode());
                paperDetails.setQuestionTypeName(questionTypeModel.getQuestionTypeName());
                paperDetails.setDone(false);
            });
            log.info("学生首次登录调查问卷抽题成功！");
        }
        // 3.最后放入整张试卷
        questionNaireAllInfoModel.setTeEvaluationPaperDetailModels(teEvaluationPaperDetailModels);
        return ItooResult.build(ItooResult.SUCCESS, "调查问卷查询成功", questionNaireAllInfoModel);
    }


    /**
     * 无参查询所有可用的评教问卷
     *
     * @return teEvaluationPaperModelList 问卷详情
     * @author 杨江涛
     * @since 2.0.0 2018-12-27 11:50:53
     */
    @Override
    public List<EvaluationPaperModel> findAllQuestionNaire() {
        // 从工具类中获取学年学期数据
        String semester = YearSemester.getYearSemesterCode(0, 0).get(0);
        return evaluationPaperDao.findAllQuestionNaire(semester);
    }

    /**
     * 无参查询所有可用的调查问卷
     *
     * @return teEvaluationPaperModelList 问卷详情
     * @author 杨江涛
     * @since 2.0.0 2018-12-27 15:57:40
     */
    @Override
    public List<EvaluationPaperModel> findAllSurveyQuestionNaire() {
        // 从工具类中获取学年学期数据
        String semester = YearSemester.getYearSemesterCode(0, 0).get(0);
        return evaluationPaperDao.findAllSurveyQuestionNaire(semester);
    }

    /**
     * 更新调查问卷的状态
     *
     * @param id     问卷id
     * @param status 问卷状态
     * @return teEvaluationPaperModelList 问卷详情
     * @author 杨江涛
     * @since 2.0.0 2018-12-27 17:36:39
     */
    @Override
    public boolean updatePaperStatus(String id, String status) {
        return evaluationPaperDao.updatePaperStatus(id, status);

    }

    /**
     * 插入调查问卷
     * @param evaluationPaperModel 整套问卷的实体
     * @return boolean 是否成功
     * @author 杨江涛
     * @since 2.0.0 2018-12-27 17:36:39
     */
    @Override
    public boolean insertQuestionnaire(EvaluationPaperModel evaluationPaperModel) {
        // 将model的对应值复制到实体中
        EvaluationPaperEntity evaluationPaperEntity = new EvaluationPaperEntity();
        BeanUtils.copyProperties(evaluationPaperModel, evaluationPaperEntity);
        // 从工具类中获取学年学期数据
        String semester = YearSemester.getYearSemesterCode(0, 0).get(0);
        evaluationPaperEntity.setSchoolYearId(semester);
        // 初始化添加的问卷你的状态为 0 草稿状态
        evaluationPaperEntity.setStatus(0);
        // 雪花算法生成主键id
        evaluationPaperEntity.setId(IdWorker.getIdStr());
        // 保存到paper表
        List<EvaluationPaperDetailModel> teEvaluationPaperDetailModelList = evaluationPaperModel.getTeEvaluationPaperDetailModelList();
        // 遍历model数据，将model的数据和paper表的id存到paperDetail表
        for (EvaluationPaperDetailModel teEvaluationPaperDetailModel : teEvaluationPaperDetailModelList) {
            // 实例化paperDetail表实体，将model数据放入实体
            EvaluationPaperDetailEntity evaluationPaperDetailEntity = new EvaluationPaperDetailEntity();
            BeanUtils.copyProperties(teEvaluationPaperDetailModel, evaluationPaperDetailEntity);
            // 将paper表实体的主键id作为外键放入paperDetail表
            evaluationPaperDetailEntity.setEvaluationPaperId(evaluationPaperEntity.getId());
            // 雪花算法生成paperDetail表的主键id
            evaluationPaperDetailEntity.setId(IdWorker.getIdStr());
            // 实例化paperMain表实体，将paperDetail表的model赋值进去
            EvaluationMainEntity evaluationMainEntity = new EvaluationMainEntity();
            BeanUtils.copyProperties(teEvaluationPaperDetailModel.getEvaluationMainModel(), evaluationMainEntity);
            // 在paperMain表生成主键id
            evaluationMainEntity.setId(IdWorker.getIdStr());
            // 将paperMain的主键放到paperDetail的外键
            evaluationPaperDetailEntity.setEvaluationMainId(evaluationMainEntity.getId());
            // 将paperDetail表的题型id放到paperMain表
            evaluationMainEntity.setEvaluationMainTypeId(evaluationPaperDetailEntity.getQuestionTypeId());
            // 将paperDetail表实体存到paperDetail表
            evaluationPaperDetailService.save(evaluationPaperDetailEntity);
            // 将paperMain表实体存到paperMain表
            evaluationMainService.insertTeEvaluationMain(evaluationMainEntity);
            teEvaluationPaperDetailModel.getEvaluationMainModel().getEvaluationSubModelList().forEach(teEvaluationSubModel -> {
                // 实例化paperSub表实体，将paperDetail表的model赋值进去
                EvaluationSubEntity evaluationSubEntity = new EvaluationSubEntity();
                BeanUtils.copyProperties(teEvaluationSubModel, evaluationSubEntity);
                // 将paperMain表的主键id放到paperSub表外键
                evaluationSubEntity.setEvaluationMainId(evaluationMainEntity.getId());
                // 雪花算法生成paperSub表的主键id
                evaluationSubEntity.setId(IdWorker.getIdStr());
                // 将paperSub表实体插入到paperSub表
                evaluationSubService.insertTeEvaluationSub(evaluationSubEntity);
            });
        }
        return this.save(evaluationPaperEntity);
    }

    /**
     * 删除问卷
     *
     * @param id 整套问卷的实体
     * @return teEvaluationPaperModelList 问卷详情
     * @author 杨江涛
     * @since 2.0.0 2019-1-15 17:02:12
     */
    @Override
    public boolean deleteWholeQuestionnaire(String id) {

        // 实例化detail数组 接收根据问卷id 查询detail表绑定该问卷的所有关系信息的detail表数据
        List<EvaluationPaperDetailModel> teEvaluationPaperDetailModelList = evaluationPaperDetailService.queryDetailInfo(id);
        if (teEvaluationPaperDetailModelList.size() > 0) {
            // 遍历paper_detail表的model数组中对应问卷的evaluation_main_id题干id 查询sub表的选项信息
            for (EvaluationPaperDetailModel teEvaluationPaperDetailModel : teEvaluationPaperDetailModelList) {
                // 实例化sub表数组，接收根据题干id查询sub表的选项数据
                List<EvaluationSubModel> evaluationSubModelList = evaluationSubService.querySubInfoByMainId(teEvaluationPaperDetailModel.getEvaluationMainId());
                if (evaluationSubModelList.size() > 0) {
                    // 删除sub表选项信息
                    for (EvaluationSubModel evaluationSubModel : evaluationSubModelList) {
                        evaluationSubService.removeById(evaluationSubModel.getId());
                    }
                }
                // 删除main表题干信息
                evaluationMainService.removeById(teEvaluationPaperDetailModel.getEvaluationMainId());
                // 删除detail表问卷绑定信息
                evaluationPaperDetailService.removeById(teEvaluationPaperDetailModel.getId());
            }
        }
        // 删除paper表问卷信息
        return  evaluationPaperService.removeById(id);
    }

    /**
     * 编辑问卷
     * @param id 问卷id
     * @return teEvaluationPaperModelList 问卷和试题实体
     * @author 杨江涛
     * @since 2.0.0 2019-1-18 16:28:10
     */
    @Override
    public EvaluationPaperModel queryQuestionnaire(String id) {
        // 查询detail表相关问卷关系信息
        List<EvaluationPaperDetailModel> teEvaluationPaperDetailModelList = evaluationPaperDetailService.queryTeEvaluationPaperDetail(id);
        // 将问卷按试题顺序排序
        teEvaluationPaperDetailModelList.sort(Comparator.comparing(EvaluationPaperDetailModel::getQuestionOrder));
        // 查询paper表相关问卷信息 放入问卷关系数组中
        EvaluationPaperEntity evaluationPaperEntity = evaluationPaperService.getById(id);
        EvaluationPaperModel evaluationPaperModel =new EvaluationPaperModel();
        BeanUtils.copyProperties(evaluationPaperEntity, evaluationPaperModel);
        evaluationPaperModel.setTeEvaluationPaperDetailModelList(teEvaluationPaperDetailModelList);
        return evaluationPaperModel;
    }

    /**
     * 更新调查问卷
     * @param evaluationPaperModel 整套问卷的实体
     * @return teEvaluationPaperModelList 问卷详情
     * @author 杨江涛
     * @since 2.0.0 2019年1月23日20:54:24
     */
    @Override
    public boolean updateQuestionnaire(EvaluationPaperModel evaluationPaperModel) {
        // 将model的对应值复制到实体中
        EvaluationPaperEntity evaluationPaperEntity = new EvaluationPaperEntity();
        BeanUtils.copyProperties(evaluationPaperModel, evaluationPaperEntity);
        // 从工具类中获取学年学期数据
        String semester = YearSemester.getYearSemesterCode(0, 0).get(0);
        evaluationPaperEntity.setSchoolYearId(semester);
        // 初始化添加的问卷你的状态为 0 草稿状态
        evaluationPaperEntity.setStatus(0);
        // 雪花算法生成主键id
        evaluationPaperEntity.setId(IdWorker.getIdStr());
        // 保存到paper表
        List<EvaluationPaperDetailModel> teEvaluationPaperDetailModelList = evaluationPaperModel.getTeEvaluationPaperDetailModelList();
        // 遍历model数据，将model的数据和paper表的id存到paperDetail表
        for (EvaluationPaperDetailModel teEvaluationPaperDetailModel : teEvaluationPaperDetailModelList) {
            // 实例化paperDetail表实体，将model数据放入实体
            EvaluationPaperDetailEntity evaluationPaperDetailEntity = new EvaluationPaperDetailEntity();
            BeanUtils.copyProperties(teEvaluationPaperDetailModel, evaluationPaperDetailEntity);
            // 将paper表实体的主键id作为外键放入paperDetail表
            evaluationPaperDetailEntity.setEvaluationPaperId(evaluationPaperEntity.getId());
            // 雪花算法生成paperDetail表的主键id
            evaluationPaperDetailEntity.setId(IdWorker.getIdStr());
            // 实例化paperMain表实体，将paperDetail表的model赋值进去
            EvaluationMainEntity evaluationMainEntity = new EvaluationMainEntity();
            BeanUtils.copyProperties(teEvaluationPaperDetailModel.getEvaluationMainModel(), evaluationMainEntity);
            // 在paperMain表生成主键id
            evaluationMainEntity.setId(IdWorker.getIdStr());
            // 将paperMain的主键放到paperDetail的外键
            evaluationPaperDetailEntity.setEvaluationMainId(evaluationMainEntity.getId());
            // 将paperDetail表的题型id放到paperMain表
            evaluationMainEntity.setEvaluationMainTypeId(evaluationPaperDetailEntity.getQuestionTypeId());
            // 将paperDetail表实体存到paperDetail表
            evaluationPaperDetailService.updateById(evaluationPaperDetailEntity);
            // 将paperMain表实体存到paperMain表
            evaluationMainService.updateById(evaluationMainEntity);
            teEvaluationPaperDetailModel.getEvaluationMainModel().getEvaluationSubModelList().forEach(teEvaluationSubModel -> {
                // 实例化paperSub表实体，将paperDetail表的model赋值进去
                EvaluationSubEntity evaluationSubEntity = new EvaluationSubEntity();
                BeanUtils.copyProperties(teEvaluationSubModel, evaluationSubEntity);
                // 将paperMain表的主键id放到paperSub表外键
                evaluationSubEntity.setEvaluationMainId(evaluationMainEntity.getId());
                // 雪花算法生成paperSub表的主键id
                evaluationSubEntity.setId(IdWorker.getIdStr());
                // 将paperSub表实体插入到paperSub表
                evaluationSubService.updateById(evaluationSubEntity);
            });
        }
        return this.updateById(evaluationPaperEntity);
    }

    /**
     * 模糊查询所有可用的问卷
     * @param  name 问卷名称
     * @param  type 问卷类型
     * @return teEvaluationPaperModelList 问卷详情
     * @author 杨江涛
     * @since 2.0.0 2019-1-25 10:31:58
     */
    @Override
    public List<EvaluationPaperModel> aboutFindAllQuestionNaire(String name, String type) {
        // 从工具类中获取学年学期数据
        String semester = YearSemester.getYearSemesterCode(0, 0).get(0);
        return evaluationPaperDao.aboutFindAllQuestionNaire(name,type,semester);
    }

    /**
         * 查询4小时内考试的问卷,将其存入redis
         * @param
         * @return
         * @author 魏恩君
         * @since 2.0.0 2019/3/19
         */
    @Override
    public Boolean questionnaireResourceRedis(){
        // 查询4小时内考试的问卷
        List<ExaminationModel> questionnaireList = evaluationPaperDao.questionnaire();
        // 4小时内的考试设置了问卷
        if (questionnaireList != null && questionnaireList.size() > 0){
            for(ExaminationModel questionnaire : questionnaireList){
                String questionnaireID = questionnaire.getEvaluationPaperId();
                if(StringUtils.isEmpty(questionnaireID)){
                    log.error("问卷ID为空");
                    return false;
                }

                String courseID = questionnaire.getCourseId();
                if(StringUtils.isEmpty(courseID)){
                    log.error("课程ID为空");
                    return false;
                }

                // 查询问卷模板详细信息，组成一套问卷
                QuestionNaireAllInfoModel questionNaireAllInfoModel = queryQuestionnaireForDB(questionnaireID);

                // 将问卷模板放进redis里
                String keyName = QUESTIONNAIRE_REDIS_INFO + ":" + courseID + ":" + questionnaireID;
                redisTemplate.opsForValue().set(keyName,questionNaireAllInfoModel,3600*4,TimeUnit.SECONDS);
            }
        }else{
            log.info("该时间段4小时内的考试没有设置问卷");
        }
        return true;
    }

       /**
     * 批量插入问卷记录表和评教建议表
     * @param courseId 课程id
     * @param paperId 问卷id
     * @param studentId 学生id
     * @param schoolYearId 学年学期id
     * @return List<EvaluationPaperDetailModel>
     * @author 魏恩君
     * @since 2.0.0 2019/3/20
     */
    @Transactional
    public List<EvaluationPaperDetailModel> insertBatchEvaluationRecord(List<EvaluationPaperDetailModel> detailModel, String schoolYearId, String courseId, String paperId, String studentId){
        if(detailModel == null || detailModel.size() < 0){
            log.warn("插入问卷记录表时问卷内容为空");
        }
        List<AssessmentAdviceEntity> assessmentAdviceEntityList = new ArrayList<>();
        List<EvaluationRecordEntity> evaluationRecordEntityList = new ArrayList<>();
        for (EvaluationPaperDetailModel evalationDetail : detailModel){
            //如果是简答题,则插入评教建议表
            if(adviceType.equals(evalationDetail.getQuestionCode())){
                AssessmentAdviceEntity adviceEntity = new AssessmentAdviceEntity();
                adviceEntity.setId(IdWorker.getIdStr());
                adviceEntity.setQuestionMainId(evalationDetail.getEvaluationMainId());
                adviceEntity.setSchoolYear(schoolYearId);
                adviceEntity.setCourseId(courseId);
                adviceEntity.setPaperId(paperId);
                adviceEntity.setStudentId(studentId);
                adviceEntity.setQuestionOrder(evalationDetail.getQuestionOrder());
                assessmentAdviceEntityList.add(adviceEntity);
                evalationDetail.setRecordId(adviceEntity.getId());
            }
            else {
                // 其他题型即单选题和多选题,则插入问卷记录表
                EvaluationRecordEntity recordEntity = new EvaluationRecordEntity();
                recordEntity.setId(IdWorker.getIdStr());
                recordEntity.setCourseId(courseId);
                recordEntity.setPaperId(paperId);
                recordEntity.setQuestionScore(evalationDetail.getScore());
                recordEntity.setQuestionCode(evalationDetail.getQuestionCode());
                recordEntity.setEvaluationMainId(evalationDetail.getEvaluationMainId());
                recordEntity.setStudentId(studentId);
                recordEntity.setSchoolYearId(schoolYearId);
                recordEntity.setQuestionOrder(evalationDetail.getQuestionOrder());
                evaluationRecordEntityList.add(recordEntity);
                evalationDetail.setRecordId(recordEntity.getId());
            }
        }
        // 批量插入
        Boolean flagPaper = evaluationPaperDao.insertPaperByBatch(evaluationRecordEntityList);
        Boolean flagAdvice = assessmentAdviceDao.insertAdviceByBatch(assessmentAdviceEntityList);
        if(!flagAdvice || !flagPaper){
            log.error("插入问卷记录表失败，学生id为{},问卷id{},课程id为{}",studentId,paperId,courseId);
            return  null;
        }
        return detailModel;
    }

    /**
     * 从数据库中查询问卷模板
     * @param paperId 问卷id
     * @return QuestionNaireAllInfoModel
     * @author 魏恩君
     * @since 2.0.0 2019/7/7
     */
    public QuestionNaireAllInfoModel queryQuestionnaireForDB(String paperId){
        // 1.定义问卷内容实体
        QuestionNaireAllInfoModel questionNaireAllInfoModel = new QuestionNaireAllInfoModel();

        // 问卷基本信息
        final EvaluationPaperEntity evaluataionbyId = evaluationPaperService.getById(paperId);
        BeanUtils.copyProperties(evaluataionbyId, questionNaireAllInfoModel);
        questionNaireAllInfoModel.setPaperId(evaluataionbyId.getId());

        List<EvaluationPaperDetailModel> teEvaluationPaperDetailModels;
        //  2.1.1.1.2.得到指定某一个问卷所有详情(题型)
        teEvaluationPaperDetailModels = evaluationPaperDetailService.queryTeEvaluationPaperDetail(paperId);
        // 2.1.1.1.2.1 将问卷所有试题排序
        teEvaluationPaperDetailModels.sort(Comparator.comparing(EvaluationPaperDetailModel::getQuestionOrder));

        // 2.1.1.1.2.2 查询出所有试题类型，放入到map中，key为题型id，value为题型信息
        List<QuestionTypeModel> questionTypeModelList = questionTypeService.queryAllQuestionType();
        Map<String, QuestionTypeModel> questionTypeModelMap = new HashMap<>(questionTypeModelList.size() * 2);
        questionTypeModelList.forEach(
                q -> questionTypeModelMap.put(q.getId(), q)
        );

        // 2.1.1.1.3.最后放入整张试卷
        questionNaireAllInfoModel.setTeEvaluationPaperDetailModels(teEvaluationPaperDetailModels);
        return questionNaireAllInfoModel;
    }

    /**
     * 查询问卷内容以及学生已答问卷记录
     * @param courseId 课程id
     * @param paperId 问卷id
     * @param studentId 学生id
     * @param schoolYearId 学年学期id
     * @return QuestionNaireAllInfoModel
     * @author 魏恩君
     * @since 2.0.0 2019/3/20
     */
    @Transactional
    @Override
    public QuestionNaireAllInfoModel queryQuestionnaireResourse(String courseId, String paperId, String studentId, String schoolYearId){
        // 定义问卷内容实体，用于返回页面
        QuestionNaireAllInfoModel questionNaireAllInfoModel = new QuestionNaireAllInfoModel();

        // 查询问卷详细逻辑
        try {
            // 1.查询redis里是否有学生问卷信息
            String keyStudent = QUESTIONNAIRE_REDIS_INFO + ":" + courseId + ":" + paperId + ":" + studentId;
            questionNaireAllInfoModel = (QuestionNaireAllInfoModel) redisTemplate.opsForValue().get(keyStudent);
            // 2.判断redis里是否有学生问卷信息
            // 2.1 如果redis里有学生问卷信息或者问卷体不为空，直接返回redis内容
            if(questionNaireAllInfoModel !=  null && questionNaireAllInfoModel.getTeEvaluationPaperDetailModels().size() > 0){
                return questionNaireAllInfoModel;
            } else {
                // 2.2 如果redis里没有学生问卷信息或者问卷体为空，则查询数据库是否有学生答题记录
                List<EvaluationRecordModel> record = evaluationPaperDao.queryEvaluationRecord(courseId,paperId,studentId,schoolYearId);
                // 3.如果数据库学生问卷记录不为空，则查询数据库学生问卷记录，并且插入到学生问卷redis
                if(record != null && record.size() > 0){
                    // 查询数据库学生问卷记录，组成一张问卷
                    questionNaireAllInfoModel = evaluationPaperService.queryNaireAndRecord(paperId,courseId,studentId,schoolYearId);
                    // 放入学生个人redis
                    redisTemplate.opsForValue().set(keyStudent,questionNaireAllInfoModel,3600*4,TimeUnit.SECONDS);
                }else{
                    // 4.如果数据库问卷记录为空，则说明学生第一次登陆，则开始生成学生个人问卷到redis和数据库
                    // 4.1 查询redis中是否有问卷模板信息
                    String keyQuestionNaire = QUESTIONNAIRE_REDIS_INFO + ":" + courseId+ ":" + paperId;
                    QuestionNaireAllInfoModel questionAllInfo = (QuestionNaireAllInfoModel) redisTemplate.opsForValue().get(keyQuestionNaire);
                    // 4.1.1 如果redis里有问卷模板信息，则插入学生答题记录表和学生问卷redis
                    if(questionAllInfo != null && questionAllInfo.getTeEvaluationPaperDetailModels().size() > 0){
                        //插入学生答题记录表
                        List<EvaluationPaperDetailModel> detailModel = insertBatchEvaluationRecord(questionAllInfo.getTeEvaluationPaperDetailModels(),schoolYearId,courseId,paperId,studentId);
                        questionNaireAllInfoModel = questionAllInfo;
                        // 放入返回实体中
                        questionNaireAllInfoModel.setTeEvaluationPaperDetailModels(detailModel);
                        //放入学生问卷redis
                        redisTemplate.opsForValue().set(keyStudent,questionNaireAllInfoModel,3600*4,TimeUnit.SECONDS);

                    }else{
                        //如果redis里没有问卷模板信息，则查询数据库问卷模板信息，放入问卷模板redis，插入学生问卷数据库，放入学生问卷redis
                        // 从数据库中查询问卷模板信息
                        questionNaireAllInfoModel = queryQuestionnaireForDB(paperId);
                        // 将问卷模板信息放入redis中
                        redisTemplate.opsForValue().set(keyQuestionNaire,questionNaireAllInfoModel,3600*4,TimeUnit.SECONDS);
                        //插入学生答题记录表
                        List<EvaluationPaperDetailModel> detailModel = insertBatchEvaluationRecord(questionNaireAllInfoModel.getTeEvaluationPaperDetailModels(),schoolYearId,courseId,paperId,studentId);
                        // 放入返回实体中
                        questionNaireAllInfoModel.setTeEvaluationPaperDetailModels(detailModel);
                        //放入学生问卷redis
                        redisTemplate.opsForValue().set(keyStudent,questionNaireAllInfoModel);
                    }
                }
            }
            return questionNaireAllInfoModel;
        }
        catch (Exception e){
            log.error("查询问卷内容和答题记录失败",e);
            return null;
        }
    }

    /**
     * 从数据库中查询试卷和答题记录
     *
     * @return questionNaireAllInfoModel
     * @author 魏恩君
     * @since 2.0.0 2019年3月20日11:26:06
     */
    @Override
    public QuestionNaireAllInfoModel queryNaireAndRecord(String paperId, String courseId, String studentId, String schoolYearId) {
        //1.定义问卷内容实体返给前端用
        QuestionNaireAllInfoModel questionNaireAllInfoModel = new QuestionNaireAllInfoModel();
        //问卷基本信息
        final EvaluationPaperEntity evaluataionbyId = evaluationPaperService.getById(paperId);
        BeanUtils.copyProperties(evaluataionbyId, questionNaireAllInfoModel);
        questionNaireAllInfoModel.setPaperId(evaluataionbyId.getId());

        List<EvaluationPaperDetailModel> teEvaluationPaperDetailModels;
        //  2.得到指定某一个问卷所有详情(题型)
        teEvaluationPaperDetailModels = evaluationPaperDetailService.queryTeEvaluationPaperDetail(paperId);
        // 2.1 将问卷所有试题排序
        teEvaluationPaperDetailModels.sort(Comparator.comparing(EvaluationPaperDetailModel::getQuestionOrder));

        // 2.2 查询出所有试题类型，放入到map中，key为题型id，value为题型信息
        List<QuestionTypeModel> questionTypeModelList = questionTypeService.queryAllQuestionType();
        Map<String, QuestionTypeModel> questionTypeModelMap = new HashMap<>(questionTypeModelList.size() * 2);
        questionTypeModelList.forEach(
                q -> questionTypeModelMap.put(q.getId(), q)
        );


        // 2.查询学生单选题和多选题答题记录
        List<EvaluationRecordModel> teEvaluationRecordModels = teEvaluationRecordDao.queryStudentDoneRecord(paperId, schoolYearId,courseId, studentId);
        Map<String, EvaluationRecordModel> teEvaluationRecordMap = new HashMap<>(teEvaluationRecordModels.size() * 2);
        teEvaluationRecordModels.forEach(tr ->{
            // 如果是多选题,则分割答案字符串
            if ("2".equals(tr.getQuestionCode())){
                if(tr.getEvaluationSubId().contains("|")){
                    String[] subArr = tr.getEvaluationSubId().split("\\|");
                    for(String sub :subArr){
                        teEvaluationRecordMap.put(tr.getEvaluationMainId() + sub,tr);
                    }
                }else{
                    teEvaluationRecordMap.put(tr.getEvaluationMainId() + tr.getEvaluationSubId(),tr);
                }
            }
            // 单选题可以直接赋答案
            else {
                teEvaluationRecordMap.put(tr.getEvaluationMainId() + tr.getEvaluationSubId(),tr);
            }
        });

        if (teEvaluationRecordMap.size() > 0) {
            // 3.1 学生答题记录不为空，需要做已答题回显
            teEvaluationPaperDetailModels.forEach(
                    tp -> {
                        tp.getEvaluationSubModelList().sort(Comparator.comparing(EvaluationSubModel::getOptionOrder));
                        QuestionTypeModel questionTypeModel = questionTypeModelMap.get(tp.getQuestionTypeId());
                        tp.setQuestionCode(questionTypeModel.getQuestionCode());
                        tp.setQuestionTypeName(questionTypeModel.getQuestionTypeName());

                        List<EvaluationSubModel> evaluationSubModelList = tp.getEvaluationSubModelList();
                        evaluationSubModelList.forEach(
                                tes -> {
                                    EvaluationRecordModel teEvaluationRecordModel = teEvaluationRecordMap.get(tes.getEvaluationMainId() + tes.getOptionId());
                                    if (teEvaluationRecordModel == null) {
                                        tes.setAnswer("false");
                                    } else {
                                        tes.setAnswer("true");
                                        tp.setDone(true);
                                    }
                                }
                        );
                    }
            );
        } else {
            // 3.2 学生答题记录为空时，显示问卷详情即可
            teEvaluationPaperDetailModels.forEach(paperDetails -> {
                // 每道题的选项按照OptionOrder进行排序
                paperDetails.getEvaluationSubModelList().sort(Comparator.comparing(EvaluationSubModel::getOptionOrder));
                QuestionTypeModel questionTypeModel = questionTypeModelMap.get(paperDetails.getQuestionTypeId());
                paperDetails.setQuestionCode(questionTypeModel.getQuestionCode());
                paperDetails.setQuestionTypeName(questionTypeModel.getQuestionTypeName());
                paperDetails.setDone(false);
            });
        }


        // 4.查询简单题是否有答题记录
        List<AssessmentAdviceModel> adviceModelList = assessmentAdviceDao.queryShortRecord(paperId,courseId,schoolYearId,studentId);
        // 如果简答题有答题记录
        if(adviceModelList.size() > 0){
            Map<String, AssessmentAdviceModel> adviceModelMap = new HashMap<>(adviceModelList.size()*2);
            adviceModelList.forEach(am ->{
                adviceModelMap.put(am.getQuestionMainId(),am);
            });
            teEvaluationPaperDetailModels.forEach(tep ->{
                AssessmentAdviceModel tr =  adviceModelMap.get(tep.getEvaluationMainId());
                if(tr != null){
                    tep.setAdvice(tr.getAdvice());
                }
            });
        }

        // 5.最后放入整张试卷
        questionNaireAllInfoModel.setTeEvaluationPaperDetailModels(teEvaluationPaperDetailModels);
        return questionNaireAllInfoModel;
    }

    @Override
    public List<EvaluationPaperModel> questionnaireEnquiryq(String switchNumber) {
        return evaluationPaperDao.questionnaireEnquiryq(switchNumber);
    }

    /**
     * 根据状态查询出不同状态的问卷
     * 王华伟---2019年5月3日11:07:45
     * @param param
     * @return
     */
    @Override
    public List<EvaluationPaperModel> selectTemplateByStatus(Map<String, Object> param){
        List<EvaluationPaperModel> evaluationPaperModelList = evaluationPaperDao.selectTemplateByStatus(param);
        return evaluationPaperModelList;
    }
}
